﻿using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace MsBuilderific.Contracts
{
    /// <summary>
    /// Object representing a Visual Studio project
    /// </summary>
    public class VisualStudioProject : IEquatable<VisualStudioProject>
    {
        #region Public properties

        /// <summary>
        /// Get or set the list of assembly names on which this projects depends
        /// </summary>
        /// <value>
        /// The list of project references
        /// </value>
        public List<String> Dependencies { get; set; }

        /// <summary>
        /// Get or set the name of the assembly generated by the project
        /// </summary>
        [XmlAttribute("Label")]
        public String AssemblyName { get; set; }

        /// <summary>
        /// Get or set the root namespace of the project
        /// </summary>
        [XmlAttribute("RootNamespace")]
        public String RootNamespace { get; set; }

        /// <summary>
        /// Get or set the project path on disk
        /// </summary>
        [XmlAttribute("Path")]
        public String Path { get; set; }

        /// <summary>
        /// Get or set the unique project identifier
        /// </summary>
        public Guid ProjectGuid { get; set; }

        /// <summary>
        /// Get the project id as a string. [Required for GraphML serialization]
        /// </summary>
        [XmlAttribute("ProjectGuid")]
        public String Id { get { return ProjectGuid.ToString(); } }

        /// <summary>
        /// Get or set a value indicating if the project is a web project
        /// </summary>
        [XmlAttribute("IsWebProject")]
        public bool IsWebProject { get; set; }

        /// <summary>
        /// Get or set a value indicating if the project is a test project
        /// </summary>
        [XmlAttribute("IsTestProject")]
        public bool IsTestProject { get; set; }

        /// <summary>
        /// Gets or sets the project's artefacts output type
        /// </summary>
        [XmlAttribute("OutputType")]
        public string OutputType { get; set; }

        #endregion

        #region Constructors

        /// <summary>
        /// Initialize a new instance of the <see cref="VisualStudioProject"/> class.
        /// </summary>
        /// <param name="projectGuid">The project's unique identifier.</param>
        /// <param name="assemblyName">Name of the assembly generated from the project.</param>
        /// <param name="rootNamespace">The project's root namespace.</param>
        /// <param name="path">The physical location of the project on the disk.</param>
        public VisualStudioProject(Guid projectGuid, string assemblyName, string rootNamespace, string path)
        {
            AssemblyName = assemblyName;
            ProjectGuid = projectGuid;
            RootNamespace = rootNamespace;
            Path = path;
            Dependencies = new List<String>();
        }

        #endregion

        #region Equality overrides

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (VisualStudioProject)) return false;
            return Equals((VisualStudioProject) obj);
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        public bool Equals(VisualStudioProject other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;

            return other.AssemblyName != null && other.AssemblyName.Equals(AssemblyName);
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return AssemblyName != null ? AssemblyName.GetHashCode() : base.GetHashCode();
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="left">The left.</param>
        /// <param name="right">The right.</param>
        /// <returns>
        /// The result of the operator.
        /// </returns>
        public static bool operator ==(VisualStudioProject left, VisualStudioProject right)
        {
            return Equals(left, right);
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="left">The left.</param>
        /// <param name="right">The right.</param>
        /// <returns>
        /// The result of the operator.
        /// </returns>
        public static bool operator !=(VisualStudioProject left, VisualStudioProject right)
        {
            return !Equals(left, right);
        }

        #endregion
    }
}
